﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.Data.Metadata.Edm;
using System.Data;
using Se7en.Admin.Model;
using System.Collections;

namespace Se7en.Admin.Model
{
    [Serializable]
    
    public class AdminContext : AdminEntities
    {
        public AdminContext() : base() { }

        public AdminContext(string connStr) : base(connStr) { }

        #region Properties

        #endregion

        #region Extensive Methods

        public SavingResults SaveAllChanges()
        {
            return SaveAllChanges(SaveOptions.DetectChangesBeforeSave);
        }

        public SavingResults SaveAllChanges(System.Data.Objects.SaveOptions option)
        {
            SavingResults result = SavingResults.Success;

            Exception err = new Exception();

            string message = "Success";

            try
            {
                int records = base.SaveChanges();
                message = string.Format("{0} record(s) was effected.", records);
            }
            #region Errors Catching
            catch (ArrayTypeMismatchException arrErr)
            {
                //write log
                err = arrErr;
                message = arrErr.InnerException.Message;
                result = SavingResults.ArrayTypeMismatch;
            }
            catch (DivideByZeroException divErr)
            {
                //write log
                err = divErr;
                message = divErr.InnerException.Message;
                result = SavingResults.ArrayTypeMismatch;
            }
            catch (FormatException formatErr)
            {
                //write log
                err = formatErr;
                message = formatErr.InnerException.Message;
                result = SavingResults.FormatException;
            }
            catch (IndexOutOfRangeException indexErr)
            {
                //write log
                err = indexErr;
                message = indexErr.InnerException.Message;
                result = SavingResults.IndexOutOfRangeException;
            }
            catch (StackOverflowException soerr)
            {
                //write log
                err = soerr;
                message = soerr.InnerException.Message;
                result = SavingResults.StackOverflowException;
            }
            catch (OutOfMemoryException oomerr)
            {
                //write log
                err = oomerr;
                message = oomerr.InnerException.Message;
                result = SavingResults.OutOfMemoryException;
            }
            catch (Exception e)
            {
                message = e.Message;
                err = e;

                result = SavingResults.UnknownError;

                if (e.InnerException != null)
                {
                    if (e.InnerException.Message.Contains("The DELETE statement conflicted with the REFERENCE constrain"))
                    {
                        message = e.InnerException.Message;
                        result = SavingResults.ReferenceConflict;
                    }
                }
            }
            #endregion
            finally
            {
                //will comment here when deploying
                if (result != SavingResults.Success)
                    throw err;
            }

            return result;
        }

        public string GetEntitySetName(dynamic entity)
        {
            Type entityType = (entity.GetType());
            if (entityType == null)
                throw new InvalidOperationException("This object is not an entity");

            EntityContainer container = this.MetadataWorkspace.GetEntityContainer(this.DefaultContainerName, DataSpace.CSpace);
            return (from entitySet in container.BaseEntitySets
                    where entitySet.ElementType.Name.Equals(entityType.Name)
                    select entitySet.Name).FirstOrDefault();
        }

        public void Update(dynamic obj)
        {
            //object oldSkill = null;
            //EntityKey key = ObjectContext.CreateEntityKey(entitySetName, obj);
            //if (ObjectContext.TryGetObjectByKey(key, out oldSkill))
            //    ObjectContext.ApplyCurrentValues(key.EntitySetName, obj);
            object currentObj = null;
            EntityKey key = this.CreateEntityKey(GetEntitySetName(obj), obj);
            if (this.TryGetObjectByKey(key, out currentObj))
                this.ApplyCurrentValues(key.EntitySetName, obj);
        }

        public void Add(dynamic newObject)
        {
            this.AddObject(GetEntitySetName(newObject), newObject);
        }

        public void DeleteAllObject(IEnumerable objects)
        {
            foreach (object o in objects)
                base.DeleteObject(o);
        }

        #endregion

    }
}
